這篇主要在講特徵處理和篩選,幫助我們在做LSTM模型時提升準確度。特徵工程其實就像在處理食材一樣,食材準備得好,料理才會更美味!同理,模型的輸入數據如果整理得好,預測效果自然就會更好。這篇文章會用隨機森林來篩選特徵,這對我們在預測投信介入後股價走勢的LSTM模型特別重要。
在處理股票數據時,我們常常會面對不同單位或數值範圍的數據,像是成交量、股價、技術指標(例如RSI)等等。這些數據的範圍差很多,要是直接丟進模型,不但不準,還有可能亂掉。所以,我們需要先把數據“標準化”或“正規化”一下,讓它們都處在同一個水平上。
標準化就像是給數據“定規矩”,把它們的值調整成差不多的尺度,像是均值為0、標準差為1,這樣模型在學習時就不會偏心某些特徵。舉個例子,我們的數據有:
Trading_Volume
open
, max
, min
, close
MA30
, MA100
, MA200
RSI
和 Bandwidth Indicator
這些數據的範圍差很大,不先標準化,模型可能會被成交量這種大數值主導,影響預測準確度。
from sklearn.preprocessing import StandardScaler
# 定義需要標準化的數值型特徵
numeric_features = ['Trading_Volume', 'open', 'max', 'min', 'close', 'MA30', 'MA100', 'MA200', 'RSI', 'Bandwidth Indicator']
# 初始化標準化工具
scaler = StandardScaler()
# 對這些特徵進行標準化處理
data[numeric_features] = scaler.fit_transform(data[numeric_features])
LSTM模型的輸入是時間序列數據,簡單來說就是一段連續的數據。我們可以把它理解成一個“時間窗口”,讓模型看到一段時間內的變化來做預測。假設我們想用過去10天的數據來預測未來5天的股價變化,這時就需要用“滑動窗口”來構建序列數據。
import numpy as np
# 定義序列構建函數
def create_sequences(data, sequence_length):
sequences = []
targets = []
for i in range(len(data) - sequence_length - 5): # 預測5天後的股價變動
seq = data[i:i + sequence_length].values
target = (data['close'].iloc[i + sequence_length + 5] - data['close'].iloc[i + sequence_length]) / data['close'].iloc[i + sequence_length] * 100
sequences.append(seq)
targets.append(target)
return np.array(sequences), np.array(targets)
# 使用過去10天的數據
sequence_length = 10
X, y = create_sequences(data, sequence_length)
這樣的處理會輸出兩個東西:
X
:過去10天的數據特徵y
:預測未來5天股價變化的百分比我們還可以從現有數據生成一些有意思的特徵。比如,針對股價的移動平均線(MA30、MA100、MA200),我們可以生成一個“突破特徵”,來看股價有沒有突破這些重要的均線。這些特徵能幫助模型更好地理解股價的趨勢。
# 生成均線突破特徵
data['MA30_breakout'] = (data['close'] > data['MA30']).astype(int)
data['MA100_breakout'] = (data['close'] > data['MA100']).astype(int)
data['MA200_breakout'] = (data['close'] > data['MA200']).astype(int)
當我們有很多特徵時,不一定每個特徵都對預測有幫助。這時,我們可以用隨機森林來幫忙篩選,讓模型只用那些對預測最有價值的特徵,這樣不但能降低模型的複雜度,也能避免過擬合(即模型過度學習訓練數據)。
我們可以用RandomForestRegressor
來幫忙評估特徵的重要性,並依據結果篩選最有幫助的特徵。
from sklearn.ensemble import RandomForestRegressor
import pandas as pd
# 取出數據中的特徵欄位
X_rf = data.drop(columns=['date', 'stock_id', 'close']) # 刪除非特徵欄位
y_rf = y # 預測目標
# 初始化隨機森林模型
rf = RandomForestRegressor()
# 訓練隨機森林模型
rf.fit(X_rf, y_rf)
# 獲取特徵重要性
importances = rf.feature_importances_
feature_names = X_rf.columns
feature_importance_df = pd.DataFrame({'Feature': feature_names, 'Importance': importances})
feature_importance_df = feature_importance_df.sort_values(by='Importance', ascending=False)
# 顯示特徵重要性
print(feature_importance_df)
隨機森林模型訓練完成後,我們可以通過特徵重要性分數來了解每個特徵對模型的貢獻。例如,移動平均線突破、成交量和技術指標(如RSI)可能對股價變化影響最大,其他特徵可能影響較小。
根據特徵重要性結果,我們可以篩選出最有影響力的特徵。通常,我們只會保留那些重要性超過某個閾值的特徵,這樣可以簡化模型,提升效能。
# 篩選出最重要的特徵
top_features = feature_importance_df[feature_importance_df['Importance'] > 0.05]['Feature']
X_top = data[top_features]